import Big from "big.js";
// 两个数字都得是数字，不然会有浮点数问题
export default class {
  static instance;
  precis;
  num_precise;

  constructor(precise, num_precise) {
    this.precis = precise;
    this.num_precise = num_precise;
  }

  static that() {
    // 当前实例
    if (!this.instance) {
      this.instance = new this(2, 2); // config.price_precise为精准度
    }
    return this.instance;
  }

  // 当需要重新加载时 删除当前实例
  static delInstance() {
    this.instance = undefined;
  }

  init(val) {
    // 初始化数字
    return val.toFixed(this.precis);
  }

  bc(formulas, precise = null) {
    // 传递字符串 执行big计算
    formulas = `(${formulas})`;
    formulas = formulas.replace(/ /g, "");
    const regex = {
      bracketRegex: /(()?)\(([^\)\(]*)\)/, // 括号的内容
      operates: [
        "([\\*\\/\\%])",
        "([\\+\\-])", // 运算符优先级问题
      ],
    };
    const result = {
      bracket: null, // 括号的内容匹配结果
      number: null, // 两数内容匹配结构
      result: "", // 两数计算的结果
      bracket_str: "", // 两数计算的公式字符串 如: 1*2
    };
    const numberRegex = (operateRegex) =>
      new RegExp(
        `((?:[-][\\d\\.]+|[\\d\\.]+))${operateRegex}((?:[-][\\d\\.]+|[\\d\\.]+))`
      );

    // eslint-disable-next-line no-cond-assign
    while ((result.bracket = regex.bracketRegex.exec(formulas))) {
      result.bracket_str = result.bracket[3]; // 括号内的字符串
      while (
        // 从公式提取两数之间的计算
        // eslint-disable-next-line no-cond-assign
        (result.number =
          numberRegex(regex.operates[0]).exec(result.bracket_str) ||
          numberRegex(regex.operates[1]).exec(result.bracket_str))
      ) {
        const firstNumber = result.number[1]; // 第一个数
        const operator = result.number[2]; // 运算符
        const secondNumber = result.number[3]; // 第二个
        const big = Big(firstNumber);
        switch (operator) {
          case "+":
            result.result = big.plus(secondNumber);
            break;
          case "-":
            result.result = big.minus(secondNumber);
            break;
          case "*":
            result.result = big.times(secondNumber);
            break;
          case "/":
            result.result = big.div(secondNumber);
            break;
          case "%":
            result.result = big.mod(secondNumber);
            break;
          // 异或可继续扩展
        }

        // 两数计算的结束 替换成 结果   `
        result.bracket_str = result.bracket_str.replace(
          result.number[0],
          result.result
        );
      }
      // 括号内部计算结束 替换为结果
      formulas = formulas.replace(result.bracket[0], result.bracket_str);
    }
    formulas = formulas.trim();
    return precise === null
      ? Big(formulas).toFixed(this.precis)
      : Big(formulas).toFixed(precise);
    // return precise === null ? lodashRound(Big(formulas), this.precis) : lodashRound(Big(formulas), precise)
  }
}
